package dai.samples.shiro.config;

import dai.samples.shiro.filter.MyFormAuthenticationFilter;
import dai.samples.shiro.filter.TestPathMatchingFilter;
import dai.samples.shiro.shiro.CustomRealm;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * 基础的shiro配置。
 * 配置中只需要配置
 * 认证和授权逻辑     Realm
 * 会话管理器        SessionsSecurityManager
 * 拦截策略         ShiroFilterFactoryBean
 */
@Configuration
public class ShiroConfig {


    /**
     * 配置自定义Realm
     * 认证主题
     * @return
     */
    @Bean
    public CustomRealm userRealm() {
        CustomRealm userRealm = new CustomRealm();
        userRealm.setAuthenticationCacheName("userRealm");
        return userRealm;
    }

    /**
     * 初始化安全管理器，此配置管理shiro的所有内容
     * @return
     */
    @Bean
    public SessionsSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        // 此内容管理shiro的session管理
        //securityManager.setSessionManager(new DefaultWebSessionManager());
        // 此内容管理shiro的缓存管理
        //securityManager.setCacheManager(null);
        // 此内容管理shiro的记住我管理
        //securityManager.setRememberMeManager(null);
        return securityManager;
    }


/*    @Bean
    public DefaultShiroFilterChainDefinition getFilterChain() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        HashMap chainMap = new HashMap();
        chainMap.putAll(getAnonMap());
        chainMap.putAll(getAuthcMap());
        definition.addPathDefinitions(chainMap);
        return definition
    }*/



    /**
     * 设置shiro过滤器，注意bean的名字 shiroFilterFactoryBean
     * 这个方法可以给filters添加新的拦截策略或者自己的拦截器，
     * 当然假如只希望使用系统默认的拦截器可以简单的使用 getFilterChain()方法
     * @return
     */
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilter() {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilter.setSecurityManager(securityManager());
        //自定义过滤
        //oauth2
        Map<String, Filter> filters = new HashMap<>(16);
        filters.put("anon", new AnonymousFilter());
        filters.put("oauth2", new TestPathMatchingFilter());
        filters.put("authc", new MyFormAuthenticationFilter());
        shiroFilter.setFilters(filters);
        // 这个参数在前后端未分离的时候，此参数用来定义不同结果的页面跳转，
        // 但是在前后端分离的情况此配置显然不适合了
        // 定义登录地址
        // shiroFilter.setLoginUrl("login");
        // 定义登录成功后地址
        // shiroFilter.setSuccessUrl("success");
        // 定义未授权地址
        // shiroFilter.setUnauthorizedUrl("unauthorized");

        // 配置对应路径需要经过的过滤器
        // 需要注意，路径的过滤是有顺序的，假如希望有些路径可以匿名访问，需要被设置在集合的最上面
        HashMap chainMap = new HashMap();
        chainMap.putAll(getAnonMap());
        chainMap.putAll(getAuthcMap());
        shiroFilter.setFilterChainDefinitionMap(chainMap);
        return shiroFilter;
    }

    /**
     * 匿名访问的列表
     * @return
     */
    private Map getAnonMap() {
        HashMap chainMap = new HashMap();
        chainMap.put("/captcha", "anon");
        chainMap.put("/logout","anon");
        chainMap.put("/layuiadmin/**", "anon");
        chainMap.put("/api/**", "anon");
        chainMap.put("/login","anon");
        chainMap.put("/h2-console/**","anon");
        return chainMap;
    }

    /**
     * 需要登录访问的列表
     * @return
     */
    private Map getAuthcMap() {
        HashMap chainMap = new HashMap();
        chainMap.put("/**", "authc");
        return chainMap;
    }

}
